package com.jml.生产者消费者.葛一鸣书;


/**
 * @author:jml
 * @date: 2019/6/19 0019 23:09
 * @description：
 *  为了提高CPU的速度，CPU有一个高速缓存Cache。在高速缓存中，读写数据的最小单位为缓存行（Cache Line），
 *  它是从主存（memory）复制到缓存（Cache）的最小单位，一般为32-128字节。同一行只要有一个变量被修改会导致整行缓存都会失效
 *
 *  如果两个变量存放在一个缓存行中时，在多线程访问中，可能会相互影响彼此的性能。
 *  如图5.4所示，假设X和Y在同一个缓存行。运行在CPU1上的线程更新了X，那么CPU2上的缓存行就会失效，同一行的Y即使没有修改也会变成无效，导致Cache无法命中。
 *  接着，如果在CPU2上的线程更新了Y，则导致CPU1上的缓存行又失效（此时，同一行的X又变得无法访问）。 如果CPU经常不能命中缓存，那么系统的吞吐量就会急剧下降。
 *
 * 多个线程同时修改同一缓存行中不同变量而导致变量全体失效的情况
 *
 *一种可行的做法就是在X，y变量的前后空间都先占据一定的位置（把它叫做padding吧，用来填充用的）。
 * 这样，当内存被读入缓存中时，这个缓存行中，只有X,y一个变量实际是有效的，xy各自占据一行，互不影响。
 */


public final class 伪共享 implements Runnable {

    public final static int NUM_THREADS = 2; // change
    public final static long ITERATIONS = 500L * 1000L * 1000L;
    //这个数组是放在缓存中的，VolatileLong的p1，p2,p3等变量，防止多个VolatileLong在同一行而进行互相影响。产生伪缓存共享问题
    private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];

    static {
        for (int i = 0; i < longs.length; i++) {
            longs[i] = new VolatileLong();
        }
    }

    private final int arrayIndex;

    public 伪共享(final int arrayIndex) {
        this.arrayIndex = arrayIndex;
    }

    public void run() {
        long i = ITERATIONS + 1;
        while (0 != --i) {
            longs[arrayIndex].value = i;
        }
    }

    public static void main(final String[] args) throws Exception {
        final long start = System.currentTimeMillis();
        runTest();
        System.out.println("duration = " + (System.currentTimeMillis() - start));
    }

    private static void runTest() throws InterruptedException {
        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new 伪共享(i));
        }

        for (Thread t : threads) {
            t.start();
        }

        for (Thread t : threads) {
            t.join();
        }
    }

    public final static class VolatileLong {

        public volatile long value = 0L;
   //     public long p1, p2, p3, p4, p5, p6, p7; // comment out
    }
}